﻿using MCUPackage;
using MCUPackage.DesignEditor;
using MCUPackage.Utils;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.ComponentModel;

namespace SxPackages.STC32G.Models
{
	/// <summary>
	/// PWM选项
	/// </summary>
	[Serializable]
	class PWMOptionBase
	{
		protected STC32GQFP64 mParent = null;

		/// <summary>
		/// 使用的引脚名集合
		/// </summary>
		protected string[] mUsePins { get; set; }

		/// <summary>
		/// 通道编码
		/// </summary>
		[Browsable(false)]
		public int Channel { get; protected set; }

		private bool mEnable = false;
		[DisplayName("使能"),
		DefaultValue(false),
		JsonProperty(Order = 100),
		Description("是否使能PWM功能"),
		PropertyOrder(0)]
		public virtual bool Enable
		{
			get => mEnable;
			set
			{
				if (value != mEnable)
				{
					if (value)
					{
						if (mParent.PinIsUsedTips(mUsePins))
						{
							return;
						}
						// 设置引脚用途
						SetPins(mUsePins);
						int max = this.Channel > 4 ? mParent.mPWMs.PWMB.Period : mParent.mPWMs.PWMA.Period;
						if (this.Duty > max)
						{
							this.Duty = max;
						}
					}
					else
					{
						// 清除占用的功能脚
						mParent.ResetPins(mUsePins);
					}
					mEnable = value;
				}
			}
		}

		[DisplayName("模式"),
		DefaultValue(PWMModes.PWM模式1),
		Description("PWM输出模式设置, 详情请查看数据手册26.9.13 捕获/比较模式寄存器1（PWMx_CCMR1）")]
		public PWMModes Mode { get; set; } = PWMModes.PWM模式1;

		private int mDuty = 1;
		[DisplayName("占空比"),
		DefaultValue(1),
		Description("占空比时间, 不能大于本组设置的周期")]
		public int Duty
		{
			get => mDuty;
			set
			{
				if (value != mDuty)
				{
					int max = this.Channel > 4 ? mParent.mPWMs.PWMB.Period : mParent.mPWMs.PWMA.Period;
					if (value > max)
					{
						value = max;
					}
					if (value < 0)
					{
						value = 0;
					}
					mDuty = value;
				}
			}
		}

		[DisplayName("使能P通道"),
		DefaultValue(true),
		Description("是否使能本通道的P通道输出")]
		public bool EnableP { get; set; } = true;

		[DisplayName("使能N通道"),
		DefaultValue(true),
		Description("是否使能本通道的N通道输出")]
		public virtual bool EnableN { get; set; } = true;

		/// <summary>
		/// 切换引脚
		/// </summary>
		/// <param name="aNew"></param>
		/// <param name="aOld"></param>
		/// <returns>是否切换成功</returns>
		protected bool SwitchPins<T>(T aNew, T aOld)
		{
			string[] newPins = TemplateHelper.GetPins(aNew);
			string[] oldPins = TemplateHelper.GetPins(aOld);

			if (this.Enable)
			{
				if (mParent.PinIsUsedTips(newPins))
				{
					return false;
				}
				// 清除占用的功能脚
				mParent.ResetPins(oldPins);
				SetPins(newPins);
			}

			mUsePins = newPins;
			return true;
		}

		protected virtual void SetPins(string[] aPins)
		{
			if (aPins == null || aPins.Length < 1)
			{
				return;
			}

			var purpose = PinPurpose.PWM1_P;
			if (Channel < 5)
			{
				purpose = PinPurpose.PWM1_P + (Channel - 1) * 2;
			}
			else
			{
				purpose = PinPurpose.PWM5 + Channel - 5;
			}

			foreach (var pin in aPins)
			{
				var opt = mParent.SetPinPurpose(pin, purpose);
				if (opt != null)
				{
					opt.Mode = GPIOMode.Push;
					opt.Speed = GPIOSpeed.Fast;
				}
				purpose++;
			}
		}

		public PWMOptionBase(STC32GQFP64 aParent)
		{
			this.mParent = aParent;
		}

		public override String ToString()
		{
			return string.Empty;
		}

		/// <summary>
		/// 初始化模板
		/// </summary>
		private const string TEMPLATE =
@"	attr.PWM_Mode      = {0};	//模式,		CCMRn_FREEZE,CCMRn_MATCH_VALID,CCMRn_MATCH_INVALID,CCMRn_ROLLOVER,CCMRn_FORCE_INVALID,CCMRn_FORCE_VALID,CCMRn_PWM_MODE1,CCMRn_PWM_MODE2
	attr.PWM_Duty      = {1};	//PWM占空比时间, 0~Period
	attr.PWM_EnoSelect = {2};	//输出通道选择,	ENO1P,ENO1N,ENO2P,ENO2N,ENO3P,ENO3N,ENO4P,ENO4N / ENO5P,ENO6P,ENO7P,ENO8P
	PWM_Configuration(PWM{3}, &attr);				//初始化PWM{3}
	PWM{3}_USE_{4}();";

		public string Generate(Dictionary<string, List<string>> aLst)
		{
			if (!this.Enable || (!this.EnableN && !this.EnableP))
			{
				return null;
			}

			string str = string.Empty;
			if (this.EnableP)
			{
				str = $"ENO{this.Channel}P";
			}
			if (this.EnableN)
			{
				if (string.IsNullOrEmpty(str))
				{
					str = $"ENO{this.Channel}N";
				}
				else
				{
					str += $" | ENO{this.Channel}N";
				}
			}

			string pins = string.Empty;
			foreach (var pin in mUsePins)
			{
				var opt = mParent.GetPinOption(pin);
				if (opt != null)
				{
					opt.ToDictionary(aLst);
					pins += pin.Replace(".", "");
				}
			}

			if (this.Channel < 5)
			{
				// 函数库中通道6的P54定义本身就是P54, 不需要改为P12
				pins = pins.Replace("P54", "P12");
			}
			return string.Format(TEMPLATE, this.Mode.ToDescription(), this.Duty, str, this.Channel, pins);
		}
	}
}
